import java.util.Timer;
import java.util.concurrent.PriorityBlockingQueue;

//定时器的构成：
//一个带优先级的阻塞队列
//队列中的每一个元素都是task任务对象
//Task中带有时间属性，队首元素为即将执行的任务
//以一个扫描线程work时刻扫描队首元素，看是否需要执行
//
public class MyTimer {
    private PriorityBlockingQueue<MyTimerTask> queue = new PriorityBlockingQueue<>();
    private Object lock = new Object();

    static class MyTimerTask implements Comparable<MyTimerTask> {
        //执行的任务
        private Runnable runnable;
        //执行时间
        private long time;

        public MyTimerTask(Runnable runnable, long time) {
            this.runnable = runnable;
            //将相对时间转化为定时器中使用的绝对时间。
            this.time = time + System.currentTimeMillis();

        }

        private void run() {
            //执行任务
            runnable.run();

        }


        @Override
        public int compareTo(MyTimerTask o) {
            //重写比较方法，将时间小的任务排在前面。
            return (int) (this.time - o.time);
        }
        //解决忙等现象

    }

    class worker extends Thread {
        //扫描线程
        @Override
        public void run() {
            while (true) {
                try {
                    MyTimerTask task = queue.take();
                    long curTime = System.currentTimeMillis();
                    if (task.time > curTime) {
                        //如果时间没到就将任务放回队列
                        queue.put(task);
                        synchronized (lock) {
                            //指定等待时间
                            lock.wait(task.time - curTime);
                        }
                    } else {
                        //时间到，运行。
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }

        // schedule 安排任务
    }
    public void schedule(Runnable command, long after) {
        MyTimerTask task = new MyTimerTask(command, after);
        queue.offer(task);
        synchronized (lock) {
            lock.notify();
        }
    }

    public MyTimer() {
        //启动worker线程
        worker worker = new worker();
        worker.start();
    }
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        Runnable command = new Runnable(){
            @Override
            public void run() {
                System.out.println("我来了");
                timer.schedule(this, 3000);
            }
        };
        timer.schedule(command, 3000);
        timer.schedule(command,2000);
    }
}

